-- 2022-8-15

---[[ 模块和包

    -- 通常 Lua语言不会设置规则(policy)
    -- 相反 Lua语言提供的是足够强大的机制供不同的开发者实现最适合自己的规则
    -- 然而 这种方法对于模块(module)而言并不是特别适用
    -- 模块系统(module system)的主要目标之一就是允许不同的人共享代码 缺乏公共规则就无法实现这样的共享

    -- Lua语言从5.1版本开始为模块和包(packege 模块的集合)定义了一系列的规则
    -- 这些规则不需要从语言中引入额外的功能 程序员可以使用目前为止我们学习到的机制实现这些规则 程序员也可以自由的使用不同的策略
    -- 当然 不同的实现可能会导致程序不能使用外部模块 或者模块不能被外部程序使用

    -- 从用户观点来看 一个模块(module)就是一些代码(要么是Lua语言编写的 要么是C语言编写的) 这些代码可以提供函数require加载 然后创建和返回一个表
    -- 这个表就像是某种命名空间 其中定义的内容是模块中导出的东西 比如函数和常量
    -- 例如所有的标准库都是模块 我们可以按照如下的方法使用数学库
    local m = require "math"
    print(m.sin(3.14))
    -- 独立解释器会使用跟如下代码等价的方式提前加载所有的标准库
    math = require "math"
    string = require "string"
    -- 这种提前加载使得我们可以不用费劲的编写代码来加载模块math就可以直接使用函数math.sin
    -- 使用表来实现模块的显著优点之一是 让我们可以像操作普通表那样操作模块 并且能利用Lua语言的所有功能实现额外的功能
    -- 在大多数语言在 模块不是第一类值(即它们不能被保存在变量中 也不能被当作参数传递给函数等) 所以那些语言需要为模块实现一套专门的机制
    -- 而在Lua语言在 我们则可以轻易的实现这些功能

    -- 例如 用户调用模块中的函数就有几种方法 其中常见的方法是
    local mod = require "mod"
    mod.foo()
    -- 用户可以为模块设置一个局部变量名称
    local m = require "mod"
    m.foo()
    -- 也可以为个别函数提供不同的名称
    local m = require "mod"
    local f = m.foo
    f()
    -- 还可以只引入特定的函数
    local f = require "mod".foo   -- (require("mod")).foo
    f()
    -- 上述这些方法的好处是无须语言的特别支持 它们使用的都素语言以及提供的功能
--]]